package dryven.view.engine.expression;

import java.util.LinkedList;
import java.util.List;

public class ViewExpression {
	
	private Iterable<ViewDataDeclaration> _declarations;
	private String _expression;
	
	public ViewExpression(String expression, Iterable<ViewDataDeclaration> declarations) {
		_declarations = declarations;
		_expression = expression;
	}
	
	public CompiledViewExpression compile() throws ExpressionCompilationException {
		String expression = _expression;
		
		String[] parts = expression.split("\\.");
		String declarationName = parts[0];
		
		ViewDataDeclaration declaration = null;
		for (ViewDataDeclaration decl : _declarations) {
			if(decl.getName().equals(declarationName)) {
				declaration = decl;
			}
		}
		
		if(declaration==null) {
			throw new ExpressionCompilationException(_expression,String.format("No declaration found for %s", declarationName));
		}
		
		List<ExpressionNode> nodes = new LinkedList<ExpressionNode>();
		
		ExpressionNode node = declaration;
		nodes.add(node);
				
		for(int partsIndex = 1;partsIndex<parts.length;++partsIndex) {
			String part = parts[partsIndex];
			
			ExpressionNode newNode = node.getChildByName(part);
			if(newNode==null) {
				StringBuilder expressionSoFar = new StringBuilder(parts[0]);
				for(int i=1;i<=(partsIndex-1);++i) {
					expressionSoFar.append('.');
					expressionSoFar.append(parts[i]);
				}
				throw new ExpressionCompilationException(_expression, String.format("Node %s was not found in the subexpression %s", part, expressionSoFar.toString()));
			} else {
				node = newNode;
				nodes.add(node);
			}
		}
		return new CompiledViewExpression(nodes);
	}
}
